// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: declaration of CImpl.
//   $Id$


#pragma once
#include "DelayedDelete.h"
#include <DOM2Events.h>

//#define COUNT_CIMPL 1
class CImplModel;
class CXFormsXFormsElement;
class CXFormsElement;
class CIdResolver;

class CImpl
	:public CDelayedDelete
{
	friend class CXFormsParse;
public:
#ifdef COUNT_CIMPL
	static unsigned long sm_Count;
#endif
	virtual void setModel(CImplModel*  pModel);
	CImpl();
	explicit CImpl(CXFormsElement* pElement);
	explicit CImpl(CXFormsXFormsElement * pXForms);
	

	virtual HRESULT init(CImpl * pParent);

	virtual HRESULT initialize(bool bForce);
	//used to put this object on the delete list.
	//	for either a model or the form.
	//	The delete list is flushed on refresh.
	virtual void notifyDelete() = 0;

	virtual HRESULT AddChild(CImpl * pChild);

	virtual HRESULT FireEvent(const CComBSTR &  sEventName,bool bBubble=true,bool bCancelable=true,void * vdContext=NULL); 

	CComBSTR m_sId;
	CComBSTR m_sContent;
	CComBSTR m_sAppearance;

	CXFormsXFormsElement * m_pXForms;
	CXFormsElement* m_pXFormsElement;

	inline BSTR UniqueId(void) const;

	//returns a resolver for scoped identifiers.
	//	normally just the document's Resolver.
	virtual CIdResolver * GetIdResolver() const;
	bool m_bisBound; 

	//made const pointer to prevent any unexpected assignation.
	//	const_cast is used in setModel()
	CImplModel* const m_pModel;
	//TODO: Abolish the distinction between m_pParent and m_pParentImpl. 
	CImpl* m_pParentImpl;
	//moved from protected for new GetIdResolver.
	CImpl * m_pParent;

	//IEventTarget interface 
	//	TODO: implement properly
	//	Does not inherit due to IDispatch, inherit and  
	//	aggregate when some of the rest of the mess is 
	//	sorted.  In particular, the diamond inheritance
	//	in some children of CImplAction.
//	virtual HRESULT addEventListener(BSTR type, IEventListener * listener, BOOL useCapture);
//	virtual HRESULT removeEventListener(BSTR type, IEventListener * listener, BOOL useCapture);
//	virtual HRESULT dispatchEvent(IDOMEvent* evt);
	//TODO: Temporary implementation of queryinterface to pretend to
	//	aggregate the eventTarget object.
	STDMETHOD(QueryInterface)(REFIID riid,void ** ppvObject);
	long getParentOrdinal();
	virtual bool IsActive() const;

	virtual HRESULT RemoveChild(CImpl* pImpl);

	/// <summary>This is called from CIdResolver::remove() to check with the owner of the CIdResolver 
	/// will allow the id to be removed. The only sitution where this method will return false 
	/// is when the owner is a xf:repeat with iterations. See Bug 954 for details.</summary>
	virtual inline bool CanRemoveIdFromResolver(void) const;

protected:
	CMap<CImpl *,CImpl *, CImpl *,CImpl *> m_Children;
	// Runs the default behaviour for various xforms events
	inline HRESULT RunDefaultBehaviour(const CComBSTR & sEventName);
	HRESULT RunCustomBehaviour(const CComBSTR & sEventName);
	HRESULT RunDeferredUpdate(void);
	// adds the control to the appropriate id list.
	virtual void AddToIdList(void);
	static bool IsWithinRepeat(CImpl * pImpl);
	virtual bool OnDeleteRequest(){return true;};
	virtual ~CImpl();

private:
	CComPtr<IEventTarget> m_pEventTargetImpl;
	CComBSTR m_sUniqueId;

	//caching of result from IsWithinRepeat, to prevent multiple tree-climbing escapades.
	bool m_bIsWithinRepeat;
	bool m_bWithinRepeatResolved;

};

inline bool CImpl::CanRemoveIdFromResolver(void) const {
	return true;
}

// Runs the default behaviour for various xforms events
inline HRESULT CImpl::RunDefaultBehaviour(const CComBSTR & /*sEventName*/)
{
	return S_FALSE;
}

inline BSTR CImpl::UniqueId(void) const
{
	return m_sUniqueId.Copy();
}
